<template>
	<view class="tui-navigation">
		<view
			class="tui-navigation-bar"
			:class="{ 'tui-bar-line': opacity > 0.85 && splitLine, 'tui-navbar-fixed': isFixed, 'tui-backdrop__filter': backdropFilter && dropDownOpacity > 0 }"
			:style="navbarInnerStyle"
		>
			<view v-if="isImmersive" class="tui-status-bar" :style="{ height: statusBarHeight + 'px' }"></view>

			<view
				v-if="title && !isCustom"
				class="tui-navigation_bar-title"
				:style="{ opacity: transparent || opacity >= maxOpacity ? 1 : opacity, color: color, paddingTop: top - statusBarHeight + 'px' }"
			>
				{{ title }}
			</view>

			<slot />
		</view>

		<view :style="{ height: height + 'px' }"></view>
	</view>
</template>

<script setup>
import { ref, reactive, toRefs, computed, watch, onBeforeMount } from 'vue'

const emit = defineEmits(['init', 'change'])

const props = defineProps({
	//NavigationBar标题
	title: {
		type: String,
		default: ''
	},
	//NavigationBar标题颜色
	color: {
		type: String,
		default: '#333'
	},
	//NavigationBar背景颜色,不支持rgb
	backgroundColor: {
		type: String,
		default: '#fff'
	},
	//是否需要分割线
	splitLine: {
		type: Boolean,
		default: false
	},
	//是否设置不透明度
	isOpacity: {
		type: Boolean,
		default: false
	},
	//不透明度最大值 0-1
	maxOpacity: {
		type: [Number, String],
		default: 1
	},
	//背景透明 【设置该属性，则背景透明，只出现内容，isOpacity和maxOpacity失效】
	transparent: {
		type: Boolean,
		default: false
	},
	//滚动条滚动距离
	scrollTop: {
		type: [Number, String],
		default: 0
	},
	/*
	 isOpacity 为true时生效
	 opacity=scrollTop /windowWidth * scrollRatio
	*/
	scrollRatio: {
		type: [Number, String],
		default: 0.3
	},
	//是否自定义header内容
	isCustom: {
		type: Boolean,
		default: false
	},
	//是否沉浸式
	isImmersive: {
		type: Boolean,
		default: true
	},
	isFixed: {
		type: Boolean,
		default: true
	},
	//是否开启高斯模糊效果[仅在支持的浏览器有效果]
	backdropFilter: {
		type: Boolean,
		default: false
	},
	//下拉隐藏NavigationBar，主要针对有回弹效果ios端
	dropDownHide: {
		type: Boolean,
		default: false
	},
	//z-index设置
	zIndex: {
		type: [Number, String],
		default: 9998
	}
})

const state = reactive({
	width: 375, //header宽度
	left: 375, //小程序端 左侧距胶囊按钮距离
	height: 44, //header高度
	top: 0,
	scrollH: 1, //滚动总高度,计算opacity
	opacity: 1, //0-1
	statusBarHeight: 0, //状态栏高度
	background: '255,255,255', //header背景色
	dropDownOpacity: 1
})

let navbarInnerStyle = ref({})
let menuButtonInfo = null
let systemInfo = null

watch(
	() => props.scrollTop,
	nVal => {
		if (props.isOpacity && !props.transparent) {
			opacityChange()
		}
	}
)

watch(
	() => props.backgroundColor,
	nVal => {
		if (val) {
			state.background = hexToRgb(val)
		}
	}
)

onBeforeMount(() => {
	state.dropDownOpacity = props.backdropFilter && 0
	state.opacity = props.isOpacity || props.transparent ? 0 : props.maxOpacity
	state.background = hexToRgb(props.backgroundColor)

	// #ifdef MP-WEIXIN
	menuButtonInfo = wx.getMenuButtonBoundingClientRect()
	// #endif

	// #ifdef MP-BAIDU
	menuButtonInfo = swan.getMenuButtonBoundingClientRect()
	// #endif

	// #ifdef MP-ALIPAY
	my.hideAddToDesktopMenu()
	// #endif

	uni.getSystemInfo({
		success: res => {
			console.log('getSystemInfo: ', res, menuButtonInfo)
			//screenHeight: 812,screenWidth: 375,statusBarHeight: 44,windowHeight: 730,windowWidth: 375
			//bottom: 80,height: 32,left: 281,right: 368,top: 48,width: 87
			systemInfo = res
			state.statusBarHeight = res.statusBarHeight
			state.width = res.windowWidth
			state.left = menuButtonInfo.left || res.windowWidth
			if (props.isImmersive) {
				state.height = menuButtonInfo.top ? menuButtonInfo.top + menuButtonInfo.height + 8 : res.statusBarHeight + 44
			}

			state.scrollH = res.windowWidth * props.scrollRatio
			state.top = menuButtonInfo.top ? menuButtonInfo.top + (menuButtonInfo.height - 32) / 2 : res.statusBarHeight + 6

			navbarInnerStyle.value = getNavbarInnerStyle()

			emit('init', {
				width: state.width,
				height: state.height,
				left: state.left,
				top: state.top,
				statusBarHeight: state.statusBarHeight,
				opacity: state.opacity,
				windowHeight: res.windowHeight
			})
		}
	})
})

const getNavbarInnerStyle = () => {
	let style = {}
	style.height = `${state.height}px`
	style.backgroundColor = `rgba(${state.background},${state.opacity})`
	style.opacity = state.dropDownOpacity
	style.zIndex = props.isFixed ? props.zIndex : 'auto'

	// 如果是各家小程序，导航栏内部的宽度需要减少右边胶囊的宽度
	// #ifdef MP
	if (menuButtonInfo) {
		const rightButtonWidth = menuButtonInfo.width + 20
		style.paddingRight = rightButtonWidth + 'px'
	}
	// #endif

	return style
}

const hexToRgb = hex => {
	let rgb = '255,255,255'
	if (hex && ~hex.indexOf('#')) {
		if (hex.length === 4) {
			let text = hex.substring(1, 4)
			hex = '#' + text + text
		}
		let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
		if (result) {
			rgb = `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`
		}
	}
	return rgb
}

const opacityChange = () => {
	if (props.dropDownHide) {
		if (props.scrollTop < 0) {
			if (state.dropDownOpacity > 0) {
				state.dropDownOpacity = 1 - Math.abs(props.scrollTop) / 30
			}
		} else {
			state.dropDownOpacity = 1
		}
	}

	let scroll = props.scrollTop <= 1 ? 0 : props.scrollTop
	let opacity = scroll / state.scrollH
	if ((state.opacity >= props.maxOpacity && opacity >= props.maxOpacity) || (state.opacity == 0 && opacity == 0)) {
		return
	}
	state.opacity = opacity > props.maxOpacity ? props.maxOpacity : opacity
	if (props.backdropFilter) {
		state.dropDownOpacity = state.opacity >= props.maxOpacity ? 1 : state.opacity
	}

	emit('change', {
		opacity: state.opacity
	})
}

const { width, left, height, top, scrollH, opacity, statusBarHeight, background, dropDownOpacity } = toRefs(state)
</script>

<style lang="scss" scoped>
.tui-navigation-bar {
	width: 100%;
	transition: opacity 0.4s;
}

.tui-backdrop__filter {
	/* Safari for macOS & iOS */
	-webkit-backdrop-filter: blur(15px);
	/* Google Chrome */
	backdrop-filter: blur(15px);
}

.tui-navbar-fixed {
	position: fixed;
	left: 0;
	right: 0;
	top: 0;
}

.tui-status-bar {
	width: 100%;
}

.tui-navigation_bar-title {
	width: 100%;
	font-size: 17px;
	line-height: 17px;
	/* #ifndef APP-PLUS */
	font-weight: 500;
	/* #endif */
	height: 32px;
	display: flex;
	justify-content: center;
	align-items: center;
}

.tui-bar-line::after {
	content: '';
	position: absolute;
	border-bottom: 1rpx solid #eaeef1;
	transform: scaleY(0.5);
	bottom: 0;
	right: 0;
	left: 0;
}
</style>
